//********************************************************************************************************
// Product Name: MapWindow.dll Alpha
// Description:  The basic module for MapWindow version 6.0
//********************************************************************************************************
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); 
// you may not use this file except in compliance with the License. You may obtain a copy of the License at 
// http://www.mozilla.org/MPL/ 
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 
// ANY KIND, either expressed or implied. See the License for the specificlanguage governing rights and 
// limitations under the License. 
//
// The Original Code is from MapWindow.dll version 6.0
//
// The Initial Developer of this Original Code is Ted Dunsford. Created 6/25/2008 10:28:22 AM
// 
// Contributor(s): (Open source contributors should list themselves and their modifications here). 
//
//********************************************************************************************************

using System;
using System.Drawing;
using Microsoft.DirectX.Direct3D;
using MapWindow.Geometries;
using MapWindow.Drawing;

namespace MapWindow.DirectX
{


    /// <summary>
    /// TexturedLineString
    /// </summary>
    public class TexturedSegmentList: PrimitiveBaseDX
    {
        #region Private Variables

        ILineSymbolizer _symbolizer;

        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new instance of TexturedLineString
        /// </summary>
        public TexturedSegmentList()
        {
         
        }

        /// <summary>
        /// creaets a new instance of TexturedSegmentList and specifies the symbolizer to use
        /// </summary>
        /// <param name="inSymbolizer">A line symbolizer to use when creating the segments</param>
        public TexturedSegmentList(ILineSymbolizer inSymbolizer)
        {
            _symbolizer = inSymbolizer;
            base.ScaleMode = _symbolizer.ScaleMode;
        }

        #endregion

        #region Methods

        

        /// <summary>
        /// Adds a new segment to this list of segments
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        public void AddSegment(Coordinate start, Coordinate end)
        {

            double sZ = start.Z;
            if (double.IsNaN(sZ)) sZ = 0F;
            double eZ = end.Z;
            if (double.IsNaN(eZ)) eZ = 0F;
            Vector vStart = new Vector(start.X, start.Y, sZ);
            Vector vEnd = new Vector(end.X, end.Y, eZ);


            Vector up = new Vector(0, 0, 1);
            Vector dir = vEnd.Subtract(vStart);
            Vector offsetDir = up.Cross(dir);
            offsetDir.Normalize();
            //Vector offset; // Perpendicular offset is in world coordinates
            //offset = offsetDir.Multiply(_symbolizer);
            //vStart = vStart.Add(offset);
            //vEnd = vEnd.Add(offset);

            Vector w = offsetDir.Multiply(_symbolizer.GetWidth() / 2);

            PositionTexturedVC vc = Vertices as PositionTexturedVC;
            if (vc != null)
            {
                float tx = Convert.ToSingle(dir.Length / w.Length);
                vc.AddCoordinate(vStart.Add(w), 0, 0);
                vc.AddCoordinate(vEnd.Add(w), tx, 0);
                vc.AddCoordinate(vStart.Subtract(w), 0, 1);
                vc.AddCoordinate(vEnd.Subtract(w), tx, 1);

            }
            else
            {
                Vertices.AddCoordinate(vStart.Add(w));
                Vertices.AddCoordinate(vEnd.Add(w));
                Vertices.AddCoordinate(vStart.Subtract(w));
                Vertices.AddCoordinate(vEnd.Subtract(w));
            }


            //float sZ = Convert.ToSingle(start.Z);
            //if (float.IsNaN(sZ)) sZ = 0F;
            //float eZ = Convert.ToSingle(end.Z);
            //if (float.IsNaN(eZ)) eZ = 0F;
            //Vector3 vStart = new Vector3(Convert.ToSingle(start.X), Convert.ToSingle(start.Y), sZ);
            //Vector3 vEnd = new Vector3(Convert.ToSingle(end.X), Convert.ToSingle(end.Y), eZ);

           
            //Vector3 up = new Vector3(0, 0, 1);
            //Vector3 dir = Vector3.Subtract(vEnd, vStart);
            //Vector3 offsetDir = Vector3.Cross(up, dir);
            //offsetDir.Normalize();
            //Vector3 offset; // Perpendicular offset is in world coordinates
            //offset = offsetDir * _symbolizer.PerpendicularOffset;
            //vStart.Add(offset);
            //vEnd.Add(offset);

            //Vector3 w = Vector3.Multiply(offsetDir, _symbolizer.GeographicWidth / 2);
            
            //PositionTexturedVC vc = Vertices as PositionTexturedVC;
            //if (vc != null)
            //{
            //    float tx = dir.Length() / w.Length();
            //    vc.AddCoordinate(Vector3.Add(vStart, w), 0, 0);
            //    vc.AddCoordinate(Vector3.Add(vEnd, w), tx, 0);
            //    vc.AddCoordinate(Vector3.Subtract(vStart, w), 0, 1);
            //    vc.AddCoordinate(Vector3.Subtract(vEnd, w), tx, 1);

            //}
            //else
            //{
            //    Vertices.AddCoordinate(Vector3.Add(vStart, w));
            //    Vertices.AddCoordinate(Vector3.Add(vEnd, w));
            //    Vertices.AddCoordinate(Vector3.Subtract(vStart, w));
            //    Vertices.AddCoordinate(Vector3.Subtract(vEnd, w));
            //}

              

          


        }

        /// <summary>
        /// Overrides the initialization in order to construct the texture as well as set up the indices
        /// if they haven't been constructed yet.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInitialize(DrawArgsDX e)
        {
            if (_symbolizer != null)
            {
                int w = (int) _symbolizer.GetWidth();
                Bitmap bmp = new Bitmap(w, w);
                Graphics g = Graphics.FromImage(bmp);
                _symbolizer.Draw(g, new Rectangle(0, 0, bmp.Width, bmp.Height));
                g.Dispose();
                if (TextureComp == null) TextureComp = new TextureComponent();
                TextureComp.TextureDX = new Texture(e.Device, bmp, Usage.AutoGenerateMipMap, Pool.Managed);

            }
            if (Indices == null || Indices.Count == 0)
            {
                Indices = new IndexCollection(Vertices.Count / 4);
            }

            base.OnInitialize(e);
        }
        

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the symbolizer for this shape.  Setting this will automatically invalidate the texture, 
        /// but not the vertex/index values.
        /// </summary>
        public ILineSymbolizer Symbolizer
        {
            get { return _symbolizer; }
            set 
            { 
                _symbolizer = value;
                Invalidate(); // by invalidating this, a new texture will be created
            }
        }




        #endregion



    }
}
